package l2ft.gameserver.model.entity.events.impl.fightclub;

import l2ft.commons.collections.MultiValueSet;
import l2ft.gameserver.model.Creature;
import l2ft.gameserver.model.Player;
import l2ft.gameserver.model.Skill;
import l2ft.gameserver.model.entity.events.fightclubmanager.FightClubPlayer;
import l2ft.gameserver.model.entity.events.fightclubmanager.FightClubTeam;
import l2ft.gameserver.model.entity.events.fightclubmanager.FightClubLastStatsManager.FightClubStatType;
import l2ft.gameserver.model.entity.events.impl.AbstractFightClub;
import l2ft.gameserver.model.entity.events.objects.CTFCombatFlagObject;
import l2ft.gameserver.model.instances.NpcInstance;
import l2ft.gameserver.utils.Location;

public class CaptureTheFlagEvent extends AbstractFightClub//TODO sprawdzic czy flaga mi zostanie po skonczeniu eventu
{
	private static final int FLAG_TO_STEAL_ID = 40024;
	private static final int FLAG_HOLDER_ID = 40025;
	private CaptureFlagTeam[] _flagTeams;
	private final int _badgesCaptureFlag;
	
	public CaptureTheFlagEvent(MultiValueSet<String> set)
	{
		super(set);
		_badgesCaptureFlag = set.getInteger("badgesCaptureFlag");
	}
	
	@Override
	public void onKilled(Creature actor, Creature victim, Skill skill)
	{
		if(actor != null && actor.isPlayable())
		{
			FightClubPlayer realActor = getFightClubPlayer(actor.getPlayer());
			if(victim.isPlayer())
			{
				realActor.increaseKills(true);
				updatePlayerScore(realActor);
				sendMessageToPlayer(realActor, MESSAGE_TYPES.HERO, "You have killed "+victim.getName());
			}
			else if(victim.isPet())
			{
				
			}
			actor.getPlayer().sendUserInfo();
		}
		
		if(victim.isPlayer())
		{
			FightClubPlayer realVictim = getFightClubPlayer(victim);
			realVictim.increaseDeaths();
			if(actor != null)
				sendMessageToPlayer(realVictim, MESSAGE_TYPES.HERO, "You have been killed by "+actor.getName());
			victim.getPlayer().sendUserInfo();
			
			CaptureFlagTeam flagTeam = getTeam(realVictim.getTeam());
			//If victim was holding flag
			if(flagTeam != null && flagTeam._holder != null && flagTeam._thisTeamHolder.playerHolding.equals(realVictim))
			{
				spawnFlag(getTeam(flagTeam._thisTeamHolder.teamFlagOwner));
				
				flagTeam._thisTeamHolder = null;
			}
		}
		
		super.onKilled(actor, victim, skill);
	}
	
	@Override
	public void startEvent()
	{
		super.startEvent();
		_flagTeams = new CaptureFlagTeam[getTeams().size()];
		int i = 0;
		for(FightClubTeam team : getTeams())
		{
			CaptureFlagTeam flagTeam = new CaptureFlagTeam();
			flagTeam._team = team;
			flagTeam._holder = spawnNpc(FLAG_HOLDER_ID, getFlagHolderSpawnLocation(team), 0);
			spawnFlag(flagTeam);
			_flagTeams[i] = flagTeam;
			i++;
		}
	}
	
	@Override
	public void stopEvent()
	{
		super.stopEvent();
		for(CaptureFlagTeam iFlagTeam : _flagTeams)
		{
			if(iFlagTeam._flag != null)
				iFlagTeam._flag.deleteMe();
			if(iFlagTeam._holder != null)
				iFlagTeam._holder.deleteMe();
			//if(iFlagTeam._enemyFlagHoldByPlayer != null)
			//	iFlagTeam._enemyFlagHoldByPlayer.despawnObject(this);
			
		}
		_flagTeams = null;
	}
	
	/**
	 * Team with Npc Holder, Npc Flag and TeamHolder - guy who is carrying the flag
	 */
	private class CaptureFlagTeam
	{
		private FightClubTeam _team;
		private NpcInstance _holder;
		private NpcInstance _flag;
		private CaptureFlagHolder _thisTeamHolder;
	}
	
	/**
	 * One guy team from @flagTeam - carrying the @enemyFlag
	 */
	private class CaptureFlagHolder
	{
		private FightClubPlayer playerHolding;
		private CTFCombatFlagObject enemyFlagHoldByPlayer;
		private FightClubTeam teamFlagOwner;
	}

	
	/**
	 * @return should it disappear?
	 */
	public boolean tryToTakeFlag(Player player, NpcInstance flag)
	{
		FightClubPlayer fPlayer = getFightClubPlayer(player);
		if(fPlayer == null)
			return false;
		if(getState() != EVENT_STATE.STARTED)
			return false;
		
		CaptureFlagTeam flagTeam = null;
		for(CaptureFlagTeam iFlagTeam : _flagTeams)
			if(iFlagTeam._flag != null && iFlagTeam._flag.equals(flag))
				flagTeam = iFlagTeam;
		System.out.println("flag team1:"+flagTeam);
		
		System.out.println("Team "+fPlayer.getTeam().getName()+" talking with "+flagTeam._team.getName());
		if(fPlayer.getTeam().equals(flagTeam._team))//player talked with his flag
		{
			giveFlagBack(fPlayer, flagTeam);
			return false;
		}
		else//player talked with enemy flag
		{
			return getEnemyFlag(fPlayer, flagTeam);
		}
	}
	
	public void talkedWithFlagHolder(Player player, NpcInstance holder)
	{
		FightClubPlayer fPlayer = getFightClubPlayer(player);
		if(fPlayer == null)
			return;
		if(getState() != EVENT_STATE.STARTED)
			return;
		
		CaptureFlagTeam flagTeam = null;
		for(CaptureFlagTeam iFlagTeam : _flagTeams)
			if(iFlagTeam._holder != null && iFlagTeam._holder.equals(holder))
				flagTeam = iFlagTeam;
		System.out.println("flag team:"+flagTeam._team.getName());
		
		if(fPlayer.getTeam().equals(flagTeam._team))//player talked with his holder
		{
			giveFlagBack(fPlayer, flagTeam);
		}
		else//player talked with enemy holder
		{
			boolean shouldFlagDissaper = getEnemyFlag(fPlayer, flagTeam);
			if(shouldFlagDissaper)
			{
				System.out.println("making "+flagTeam._team.getName()+" flag dissapear");
				//flagTeam._flag.deleteMe(); TODO
				//flagTeam._flag = null;
			}
		}
	}
	
	/**
	 * @FPlayer from talked to Flag/Holder of @enemyFlagTeam
	 */
	private boolean getEnemyFlag(FightClubPlayer fPlayer, CaptureFlagTeam enemyFlagTeam)
	{
		CaptureFlagTeam goodTeam = getTeam(fPlayer.getTeam());
		Player player = fPlayer.getPlayer();
		System.out.println("get enemy flag");
		if(enemyFlagTeam._flag != null)
		{
			//Adding flag
			CTFCombatFlagObject flag = new CTFCombatFlagObject();
			flag.spawnObject(this);
			player.getInventory().addItem(flag.getItem());
			player.getInventory().equipItem(flag.getItem());
			
			
			CaptureFlagHolder holder = new CaptureFlagHolder();
			holder.enemyFlagHoldByPlayer = flag;
			holder.playerHolding = fPlayer;
			holder.teamFlagOwner = enemyFlagTeam._team;
			goodTeam._thisTeamHolder = holder;
			
			enemyFlagTeam._flag.deleteMe();
			enemyFlagTeam._flag = null;
			
			sendMessageToTeam(enemyFlagTeam._team, MESSAGE_TYPES.CRITICAL, "Someone stolen your Flag!");
			sendMessageToTeam(goodTeam._team, MESSAGE_TYPES.CRITICAL, fPlayer.getPlayer().getName()+" stolen flag from "+enemyFlagTeam._team.getName()+" Team!");
			
			return true;
		}
		return false;
	}
	
	private CaptureFlagTeam getTeam(FightClubTeam team)
	{
		for(CaptureFlagTeam iFlagTeam : _flagTeams)
			if(iFlagTeam._team != null && iFlagTeam._team.equals(team))
				return iFlagTeam;
		return null;
	}
	
	/**
	 * @param fPlayer - player talking to holder/flag
	 * @param flagTeam - his flagTeam
	 */
	private void giveFlagBack(FightClubPlayer fPlayer, CaptureFlagTeam flagTeam)
	{
		System.out.println("give flag back");
		CaptureFlagHolder holdingTeam = flagTeam._thisTeamHolder;
		if(holdingTeam != null && fPlayer.equals(holdingTeam.playerHolding))
		{
			holdingTeam.enemyFlagHoldByPlayer.despawnObject(this);
			
			spawnFlag(getTeam(holdingTeam.teamFlagOwner));
			
			flagTeam._thisTeamHolder = null;
			flagTeam._team.incScore(1);
			updateScreenScores();

			for(FightClubTeam team : getTeams())
				if(!team.equals(flagTeam._team))
						sendMessageToTeam(holdingTeam.teamFlagOwner, MESSAGE_TYPES.CRITICAL, flagTeam._team.getName()+" team gained score!");
			sendMessageToTeam(flagTeam._team, MESSAGE_TYPES.CRITICAL, "You have gained score!");
			
			fPlayer.increaseEventSpecificScore("capture");
		}
	}
	
	private Location getFlagHolderSpawnLocation(FightClubTeam team)
	{
		return getMap().getKeyLocations()[team.getIndex()-1];
	}
	
	private void spawnFlag(CaptureFlagTeam flagTeam)
	{
		NpcInstance flag = spawnNpc(FLAG_TO_STEAL_ID, getFlagHolderSpawnLocation(flagTeam._team), 0);
		flag.setName(flagTeam._team.getName()+" Flag");
		flag.broadcastCharInfo();
		flagTeam._flag = flag;
		System.out.println("spawning "+flagTeam._team.getName()+" flag");
	}
	
	@Override
	protected int getBadgesEarned(FightClubPlayer fPlayer, int currentValue)
	{
		currentValue += addMultipleBadgeToPlayer(fPlayer, FightClubStatType.CAPTURE_FLAG, fPlayer.getEventSpecificScore("capture"), _badgesCaptureFlag, fPlayer.getSecondsSpentOnEvent());
		return super.getBadgesEarned(fPlayer, currentValue);
	}
	
	@Override
	public String getVisibleTitle(Player player, String currentTitle, boolean toMe)
	{
		FightClubPlayer fPlayer = getFightClubPlayer(player);
		
		if(fPlayer == null)
			return currentTitle;
		
		return "Kills: "+fPlayer.getKills(true)+" Deaths: "+fPlayer.getDeaths();
	}
}
